const { ValidationError } = require("../utils/errors");
const {validate} = require("validate.js");
const blogTypeModel = require("../dao/model/blogTypeModule");
const { addBlogDao, findBlogByPageDao, findBlogByIdDao, updateBlogDao, deleteBlogDao } = require("../dao/blogDao");
const { addBlogToType, reduceBlogToType } = require("../dao/blogTypeDao");
const { formatResponse, handleDataPattern, handleTOC } = require("../utils/tool");
const { deleteMessageByBlogIdDao } = require("../dao/messageDao");

// 扩展验证规则
validate.validators.categoryIdIsExist = async function (value) {
  const blogTypeInfo = blogTypeModel.findByPk(value);
  if(blogTypeInfo) {
    return;
  }
  return "CategoryId is Not Exist";
}
// 添加一个博客
module.exports.addBlogService = async function (blogInfo) {
  // 首先第一个要处理的是TOC
  blogInfo = handleTOC(blogInfo);

  // 将处理好的TOC格式转为字符串
  blogInfo.toc = JSON.stringify(blogInfo.toc);

  // 初始化新文章的其他信息
  blogInfo.scanNumber = 0; // 阅读量初始化为0
  blogInfo.commentNumber = 0; // 评论数初始化为0

  // 定义验证规则
  const blogRules = {
    title: {
      presence: {
        allowEmpty: false
      },
      type: "string"
    },
    description: {
      presence: {
        allowEmpty: true
      },
      type: "string"
    },
    toc: {
      presence: {
        allowEmpty: true
      },
      type: "string"
    },
    htmlContent: {
      presence: {
        allowEmpty: false
      },
      type: "string"
    },
    thumb: {
      presence: {
        allowEmpty: true
      },
      type: "string"
    },
    scanNumber: {
      presence: {
        allowEmpty: false
      },
      type: "integer"
    },
    commentNumber: {
      presence: {
        allowEmpty: false
      },
      type: "integer"
    },
    createDate: {
      presence: {
        allowEmpty: false
      },
      type: "string"
    },
    categoryId: {
      presence: true,
      type: "string",
      categoryIdIsExist: true
    },
  }

  // 接下来对传递过来的数据进行验证
  try{
    await validate.async(blogInfo, blogRules);
    const data = await addBlogDao(blogInfo);
    // 文章新增，对应的文章分类数量
    await addBlogToType(blogInfo.categoryId);
    return formatResponse(0, "", data);
  } catch(err) {
    // 验证未通过
    throw new ValidationError('数据验证失败');
  }
}

// 分页获取博客
module.exports.findBlogByPageService = async function (pageInfo) {
  const data = await findBlogByPageDao(pageInfo);
  const rows = handleDataPattern(data.rows);
  // TOC数据类型转换
  rows.forEach(item => {
    item.toc = JSON.parse(item.toc);
  });
  return formatResponse(0, "", {
    "total": data.count,
    "rows": rows
  });
}

// 获取单篇文章
module.exports.findBlogByIdService = async function (id, auth) {
  
  const data = await findBlogByIdDao(id);
  // 首先需要重新处理toc
  data.dataValues.toc = JSON.parse(data.dataValues.toc);
  // 根据auth是否有值决定浏览数自增
  if(!auth) {
    data.scanNumber++;
    await data.save();
  }
  return formatResponse(0, "", data.dataValues);
}

// 修改一篇博客
module.exports.updateBlogService = async function (id, newBlogInfo) {
  // 首先判断正文内容有没有改变
  if(newBlogInfo.htmlContent) {
    // 文章的正文内容改变，需要重新处理TOC目录
    blogInfo = handleTOC(blogInfo);
    // 将处理好的TOC格式转为字符串
    blogInfo.toc = JSON.stringify(blogInfo.toc);
  }
  const data = await findBlogByIdDao(id);
  if(newBlogInfo.categoryId && data.dataValues.categoryId !== +newBlogInfo.categoryId) {
    await addBlogToType(newBlogInfo.categoryId);
    if(data.dataValues.categoryId) {
      await reduceBlogToType(data.dataValues.categoryId);
    }
  }
  const {dataValues} = await updateBlogDao(id, newBlogInfo);
  return formatResponse(0, "", dataValues);
}

// 删除一篇博文
module.exports.deleteBlogService = async function (id) {
  // 根据id查询到该篇文章的信息
  const data = await findBlogByIdDao(id);
  // 找到该文章对应的分类，该分类下的文章数量自减
  await reduceBlogToType(data.dataValues.categoryId);
  // 该文章下的评论也要一并删除
  await deleteMessageByBlogIdDao(id)
  // 最后进行删除操作
  await deleteBlogDao(id);
  return formatResponse(0, "", true);
}